package com.cq.hd.common.utils;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @description: Redis工具类
 * @author: mYunYu
 * @date: 2021/7/7 16:09
 * @version: v1.0
 */
@Slf4j
@Component
public class RedisUtil {

    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /**
     * @Description: key是否在redis存在
     * @Param: [key]
     * @Return: java.lang.Boolean   true 存在 false反之
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:09
     */
    public Boolean hasKey(String key) {
        return stringRedisTemplate.hasKey(key);
    }

    /**
     * @Description: 指定缓存失效时间
     * @Param: [key, time, timeUnit]
     * @Return: java.lang.Boolean
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:10
     */
    public Boolean expire(String key, long time, TimeUnit timeUnit) {
        try {
            if (time > 0) {
                return stringRedisTemplate.expire(key, time, timeUnit);
            }
        } catch (Exception e) {
            log.error("指定缓存失效时间失败", e);
        }
        return false;
    }

    /**
     * @Description: 获取过期时间
     * @Param: [key]
     * @Return: long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:10
     */
    public long getExpire(String key) {
        try {
            Long expire = stringRedisTemplate.getExpire(key);
            if (expire != null) {
                return expire;
            }
            return 0;
        } catch (Exception e) {
            log.error("获取过期时间失败", e);
        }
        return 0;
    }

    /**
     * @Description: 删除缓存
     * @Param: [key]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:10
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (!StringUtils.isEmpty(key)) {
            if (key.length == 1) {
                stringRedisTemplate.delete(key[0]);
            } else {
                stringRedisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    public void del(Collection<String> collection) {
        if (CollectionUtil.isNotEmpty(collection)) {
            stringRedisTemplate.delete(collection);
        }
    }

    /* ============================================== String ============================================== */

    /**
     * @Description: 获取字符串缓存
     * @Param: [key]
     * @Return: java.lang.String
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:10
     */
    public String get(String key) {
        return key == null ? null : stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * @Description: 设置字符串缓存
     * @Param: [key, value]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:10
     */
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * @Description: 设置字符串缓存并指定失效时间
     * @Param: [key, value, time, timeUnit]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:11
     */
    public void set(String key, String value, long time, TimeUnit timeUnit) {
        if (time > 0) {
            stringRedisTemplate.opsForValue().set(key, value, time, timeUnit);
        }
    }

    /**
     * @Description: 递增
     * @Param: [key]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:11
     */
    public Long incr(String key) {
        return stringRedisTemplate.opsForValue().increment(key);
    }

    /**
     * @Description: 指定数值递增
     * @Param: [key, delta]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:11
     */
    public Long incr(String key, long delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * @Description: 递减
     * @Param: [key]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:11
     */
    public Long decr(String key) {
        return stringRedisTemplate.opsForValue().decrement(key);
    }

    /**
     * @Description: 指定数值递减
     * @Param: [key, delta]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:11
     */
    public Long decr(String key, long delta) {
        return stringRedisTemplate.opsForValue().decrement(key, delta);
    }

    /* ============================================== Hash ============================================== */

    /**
     * @Description: 获取Hash表
     * @Param: [key, item]
     * @Return: java.lang.Object
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:11
     */
    public Object hGet(String key, String item) {
        return stringRedisTemplate.opsForHash().get(key, item);
    }

    /**
     * @Description: 获取Hash表对应的所有键值
     * @Param: [key]
     * @Return: java.util.Map<java.lang.Object, java.lang.Object>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:11
     */
    public Map<Object, Object> hmGet(String key) {
        return stringRedisTemplate.opsForHash().entries(key);
    }

    /**
     * @Description: 添加值到Hash表
     * @Param: [key, hashKey, value]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:12
     */
    public void hmSet(String key, Object hashKey, Object value) {
        stringRedisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * @Description: 批量添加值到Hash表
     * @Param: [key, map]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:12
     */
    public void hmSetAll(String key, Map<String, Object> map) {
        stringRedisTemplate.opsForHash().putAll(key, map);
    }

    /**
     * @Description: 删除hash表中的值
     * @Param: [key, item]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:12
     */
    public void hDel(String key, Object... item) {
        stringRedisTemplate.opsForHash().delete(key, item);
    }

    /**
     * @Description: 判断hash表中是否有该项的值
     * @Param: [key, item]
     * @Return: boolean
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:12
     */
    public boolean hHasKey(String key, String item) {
        return stringRedisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * @Description: Hash递增
     * @Param: [key, item, data]
     * @Return: double
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:12
     */
    public double hIncr(String key, String item, double data) {
        return stringRedisTemplate.opsForHash().increment(key, item, data);
    }

    /**
     * @Description: Hash递减
     * @Param: [key, item, data]
     * @Return: double
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:12
     */
    public double hDecr(String key, String item, double data) {
        return stringRedisTemplate.opsForHash().increment(key, item, -data);
    }

    /* ============================================== set ============================================== */

    /**
     * @Description: 获取Set缓存中的所有值
     * @Param: [key]
     * @Return: java.util.Set<java.lang.String>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:12
     */
    public Set<String> getSet(String key) {
        return stringRedisTemplate.opsForSet().members(key);
    }

    /**
     * @Description: 通过value从一个set中查询, 是否存在
     * @Param: [key, value]
     * @Return: java.lang.Boolean
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:13
     */
    public Boolean setSetHasKey(String key, Object value) {
        return stringRedisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * @Description: 将数据放入set缓存
     * @Param: [key, values]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:13
     */
    public Long setSet(String key, String... values) {
        return stringRedisTemplate.opsForSet().add(key, values);
    }

    /**
     * @Description: 获取set缓存的长度
     * @Param: [key]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:13
     */
    public Long getSetSize(String key) {
        return stringRedisTemplate.opsForSet().size(key);
    }

    /* ============================================== zSet ============================================== */

    /**
     * @Description: 获取zSet列表
     * @Param: [key, start, end]
     * @Return: java.util.Set<java.lang.String>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:13
     */
    public Set<String> getZSetRange(String key, long start, long end) {
        return stringRedisTemplate.opsForZSet().range(key, start, end);
    }

    /**
     * @Description: 获取 zSet 长度
     * @Param: [key]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:14
     */
    public Long getZSetSize(String key) {
        return stringRedisTemplate.opsForZSet().size(key);
    }

    /**
     * @Description: 获取 zSet 列表
     * @Param: [key]
     * @Return: java.util.Set<java.lang.String>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:14
     */
    public Set<String> getReverseRange(String key) {
        return stringRedisTemplate.opsForZSet().reverseRange(key, 0, 1);
    }

    public Set<String> getReverseRange(String key, long v1, long v2) {
        return stringRedisTemplate.opsForZSet().reverseRange(key, v1, v2);
    }

    /**
     * @Description: 获取权重
     * @Param: [key, obj]
     * @Return: java.lang.Double
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:14
     */
    public Double getScore(String key, Object obj) {
        return stringRedisTemplate.opsForZSet().score(key, obj);
    }

    /**
     * @Description: 获取排名
     * @Param: [key, obj]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:14
     */
    public Long getRank(String key, Object obj) {
        return stringRedisTemplate.opsForZSet().rank(key, obj);
    }

    /**
     * @Description: 移除zSet中某个元素
     * @Param: [key, obj]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:14
     */
    public void zSetRemove(String key, Object obj) {
        stringRedisTemplate.opsForZSet().remove(key, obj);
    }

    /**
     * @Description: 移除zSet中指定范围内元素
     * @Param: [key, start, end]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:15
     */
    public void removeRange(String key, long start, long end) {
        stringRedisTemplate.opsForZSet().removeRange(key, start, end);
    }

    /**
     * @Description: 添加元素到zSet中
     * @Param: [key, val, score]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:15
     */
    public void zSetAdd(String key, String val, double score) {
        stringRedisTemplate.opsForZSet().add(key, val, score);
    }

    /**
     * @Description: 移除值为value的缓存
     * @Param: [key, values]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:15
     */
    public Long setRemove(String key, Object... values) {
        return stringRedisTemplate.opsForSet().remove(key, values);
    }

    /* ============================================== List ============================================== */

    /**
     * @Description: 获取List缓存
     * @Param: [key, start, end]
     * @Return: java.util.List<java.lang.String>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:15
     */
    public List<String> getList(String key, long start, long end) {
        return stringRedisTemplate.opsForList().range(key, start, end);
    }

    /**
     * @Description: 获取List缓存的长度
     * @Param: [key]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:15
     */
    public Long getListSize(String key) {
        return stringRedisTemplate.opsForList().size(key);
    }

    /**
     * @Description: 通过索引获取list缓存中的值
     * @Param: [key, index]
     * @Return: java.lang.Object
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:15
     */
    public Object getListByIndex(String key, long index) {
        return stringRedisTemplate.opsForList().index(key, index);
    }

    /**
     * @Description: 将值插入List缓存右侧
     * @Param: [key, value]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:16
     */
    public void rightPush(String key, String value) {
        stringRedisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * @Description: 批量将值插入List缓存右侧
     * @Param: [key, value]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:16
     */
    public void rightPushAll(String key, List<String> value) {
        stringRedisTemplate.opsForList().rightPushAll(key, value);

    }

    /**
     * @Description: 获取List缓存右侧弹出一个值
     * @Param: [key]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:16
     */
    public void rightPop(String key) {
        stringRedisTemplate.opsForList().rightPop(key);
    }

    /**
     * @Description: 获取List缓存右侧弹出一个值并设置等待时间
     * @Param: [key, time(当缓存中值不存在时等待time), timeUnit]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:16
     */
    public void rightPop(String key, long time, TimeUnit timeUnit) {
        stringRedisTemplate.opsForList().rightPop(key, time, timeUnit);
    }

    /**
     * @Description: 将值插入List缓存左侧
     * @Param: [key, value]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:17
     */
    public void leftPush(String key, String value) {
        stringRedisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * @Description: 批量将值插入List缓存左侧
     * @Param: [key, value]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:17
     */
    public void leftPushAll(String key, List<String> value) {
        stringRedisTemplate.opsForList().leftPushAll(key, value);
    }

    /**
     * @Description: 获取List缓存左侧弹出一个值
     * @Param: [key]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:17
     */
    public void leftPop(String key) {
        stringRedisTemplate.opsForList().leftPop(key);
    }

    /**
     * @Description: 获取List缓存左侧弹出一个值并设置等待时间
     * @Param: [key, time, timeUnit]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:17
     */
    public void leftPop(String key, long time, TimeUnit timeUnit) {
        stringRedisTemplate.opsForList().leftPop(key, time, timeUnit);
    }

    /**
     * @Description: 通过索引修改list中的某条数据
     * @Param: [key, index, value]
     * @Return: void
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:17
     */
    public void updateListByIndex(String key, long index, String value) {
        stringRedisTemplate.opsForList().set(key, index, value);
    }

    /**
     * @Description: 移除N个值为value
     * @Param: [key, count, value]
     * @Return: java.lang.Long
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:17
     */
    public Long removeListByValue(String key, long count, Object value) {
        return stringRedisTemplate.opsForList().remove(key, count, value);
    }

    /**
     * @Description: 正则匹配redis key
     * @Param: [pattern]
     * @Return: java.util.Set<java.lang.String>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:18
     */
    public Set<String> keys(String pattern) {
        return stringRedisTemplate.keys(pattern);
    }

    /**
     * @Description: 批量获取数据
     * @Param: [keys]
     * @Return: java.util.List<java.lang.String>
     * @Auther: mYunYu
     * @Date: 2021/7/7 16:18
     */
    public List<String> multiGet(Set<String> keys) {
        return stringRedisTemplate.opsForValue().multiGet(keys);

    }
}
